iT邦幫忙

第 11 屆 iThome 鐵人賽

DAY 3
1

這幾天均會說明TF的資料處理。雖然資料處理真的非常瑣碎也煩人,常常會處理到起瘋。但資料處理對一個ML project或者Data science project非常重要。俗話說的好 "Garbage in , Garbage out !",所以真的要很小心注意資料處理的步驟,有時候Model train壞,只是因為資料處理的步驟出了問題,而資料處理就會佔掉您60% ~ 70%的時間。因此,若您可以熟悉這些語法,或許可以加速您在資料處理的步驟。

一般來說,以一個影像辨識的data shape,我們會將資料擺成 [batch, height(row), width(columns),channel] 。Ex: [128,64,64,1]。因次第一個說明的就是最常看到的reshape

Reshape:

常常我們可能想資料轉換樣式,或者是把shape轉成我們想要的樣式 Ex: [64,32,32] -> [64, 32*32],將想是將一個image[b,h,w,3] 轉成 [b,pixcel,3]。類似將一個2維度的Matrix轉成一個1維度的array。

#Create samples
a = tf.random.normal([6,32,32,3])
#Reshape to different type
tf.reshape(a,[6,32*32,3]).shape
#Output:TensorShape([6, 1024, 3])
tf.reshape(a,[6,-1,3]).shape
#Output:TensorShape([6, 1024, 3])

https://ithelp.ithome.com.tw/upload/images/20190918/20119971zlyQ95QPB8.png
[註]: 將reshape中的欄位設為-1,他會自動計算

或者也可以一次使用兩次reshape來轉換資料。例如:

tf.reshape(tf.reshape(a,[6,-1]),[6,16,-1,3]).shape
#Output:TensorShape([6, 16, 64, 3])

如果要將資料轉回來,Ex: [6,1024,3] -> [6,32,32,3]。要保留原有shpae的資訊就可以轉回來。

Transpose:

當你想要將matrix的欄位對調,Ex; [6,32,32,3] -> [6,32,3,32],就可以使用transpose來對調。有時候我們會將[b,h,w,3] -> [b,3,h,w] (Pytorch格式),就可以使用tf.transpose來轉。

tf.transpose(a,perm=[0,1,3,2]).shape
#Output:TensorShape([6, 32, 3, 32])

Expand_dims:

當如果您想到增加一個維度,例如原本你有一個 [32,32,3]的圖,但您想新增新的一維度來記錄他的資料量,或者一個batch的量。就可以使用tf.expamd_dims來新增。

a = tf.random.normal([32,32,3])
tf.expand_dims(a,axis=0).shape
#Output:TensorShape([1,32,32,3])

Broadcasting:

Broadcast的function就是broadcast數值,但實際上,儲存或者variable size都是沒有變化,不會去複製data。因此,在儲存效率上,是有較好的。簡單的案例就像是我們在做Linear regression的時候,在 X*W+b的時候,通常b會以broadcast的方式來執行 (之後會有實作Linear regression)。

  • 概念: 當a 和 b 維度不一致時 (a=[4,32,32,3], b=[3]),做broadcast的時候,會先向右靠齊然後增加維度相加 (b會broadcast -> [3] -> [1,1,1,3] -> [4,32,32,3] 和a做運算),也就是說他會exapand成相同的size。
  • 應用情境:今天公司有4個部們,40個員工,以及他們每個月的薪資,因為今天公司發大財,想要幫所有員工加薪,因此我們可能會組成一個matrix A = [4,40,12],現在我們有另外一個每個月調薪的matrix B = [40,1]。這時候就可以用broadcast將所有人一次加薪,假如今天公司想要針對每個月加不一致的薪水,matrix B = [12]。我也好想加薪

(註: broadcast的時候,要對齊最右邊的那個維度,若非1,則必須相等)

x = tf.random.normal([4,40,12])
(x + tf.random.normal([40,1])).shape
#Output:TensorShape([4, 40, 12])

(註1: 因為broadcast是一種內建的優化方式,TF會自斷判斷是否可以broadcast,不用特別寫broadcast)
(註2:假如你想broadcast且b的維度變成broadcast 後的相同維度,可以參考tf.broadcast_to 以及tf.tile)

Merge and Split:

假如我今天有兩個資料,想要以row wise的方式合併在一起,Ex: (#row,#cols) A[6,12] + B[6,12] = [12,12]。此時,可以使用tf.concat來合併資料。

a = tf.ones([6,32,3])
b = tf.ones([6,32,3])
tf.concat([a,b],axis=0).shape
#Output:TensorShape([12, 32, 3])

此外,可以透過axis來調控你要合併by哪一個axis

a = tf.ones([6,32,3])
b = tf.ones([6,32,3])
tf.concat([a,b],axis=1).shape
#Output:TensorShape([6, 64, 3])

假如我今天有兩個資料,想要以column wise的方式合併在一起,類似新增一個column,Ex: (#row,#cols) A[6,12] + B[6,12] = [2,6,12]。此時,可以使用tf.stack來合併資料。

a = tf.ones([6,32,3])
b = tf.ones([6,32,3])
tf.stack([a,b],axis=0).shape
#Output:TensorShape([2,6, 64, 3])

Split的話,這邊會比較unstacksplit的用法
unstack與stack正好相反,也就是拿掉Column

a = tf.ones([2,32,3])
aa,ab= tf.unstack(a,axis=0)
aa.shape
#Output:TensorShape([32, 3])
data_all = tf.unstack(a,axis=1)
data_all[0].shape
#Output:TensorShape([2, 3])
len(data_all)
#Output:32

split的話就會比較直觀,就是直接針對指定Column然後切幾分這樣。

data_all = tf.split(a,axis=1,num_or_size_splits=2)
data_all[0].shape
#Output:TensorShape([2, 16, 3])
len(data_all)
#Output:2

小結:

這次是簡易的一些TF的資料處理的語法,資料處理真的很繁雜,真的需要耐性將資料處理乾淨,且確認沒有問題才能將資料放入模型。大家可以玩玩看,並且我下面連結我會放上是示範的Colab[註1]。若有任何問題大家可以討論交流,感謝您的閱讀。

一日一梗圖:
https://ithelp.ithome.com.tw/upload/images/20190918/20119971xYJVZ6U1q2.png

註一 TF_basic_Colab


上一篇
[Day-2] Tensorflow 基本語法 - Part I
下一篇
[Day-4] Tensorflow 基本語法 - Part III
系列文
Towards Tensorflow 2.030
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言